#include "String.h"
// string()
//     :_str(new char[1])
// {
//     //空参构造也需要开一个空间放\0
//     _str[0] = '\0';
// }

size_t String::npos = -1;

// 构造函数
String::String(const char *str)
{
	_size = _capacity = strlen(str);
	_str = new char[_capacity + 1];
	strcpy(_str, str);
}

// 交换
void String::Swap(String &s)
{
	std::swap(_str, s._str);
	std::swap(_size, s._size);
	std::swap(_capacity, s._capacity);
}

// 深拷贝——传统写法
/*
String::String(const String &s)
	: _str(new char[strlen(s._str) + 1]) // 申请和s一样的空间
	,_size(0)
	,_capacity(0)
{
	strcpy(_str, s._str); // 拷贝s的数据
	_size = s._size;
	_capacity = s._capacity;
}
*/

// 深拷贝——现代写法(拿别人的成果)
String::String(const String &s)
	: _str(nullptr) // 一定要置空，否则交换给tmp时，tmp析构的是随机值，会报错
	, _size(0)
	, _capacity(0)
{
	String tmp(s._str);
	this->Swap(tmp);
	//_size = s._size;
	//_capacity = s._capacity;
}

// 赋值拷贝——传统写法
/*
String &String::operator=(const String &s)
{
	if (this != &s)
	{
		delete[] _str; // 先释放空间，否则会有内存泄漏
		_str = new char[strlen(s._str) + 1];
		strcpy(_str, s._str);
		_size = s._size;
	}

	return *this;
}
*/
/*
//赋值拷贝——现代写法
String &String::operator=(const String &s){
	if (this != &s)
	{

		//不仅交换到了需要的数据，还把需要析构的数据交给tmp，tmp生命周期一到就自动析构了
		String tmp(s);
		this->Swap(tmp);

	}

	return *this;
}
*/

// 赋值拷贝——更简便的写法
String &String::operator=(String s)
{
	if (this != &s)
	{
		// 都不需要拷贝tmp，传值的时候已经拷贝一次了
		//swap(_str, s._str);
		this->Swap(s);
	}

	return *this;
}

String::iterator String::begin()
{
	return _str;
}
String::iterator String::end()
{
	return _str + _size;
}

size_t String::size() const
{
	return _size;
}

size_t String::capacity() const
{
	return _capacity;
}

const char *String::c_str() const
{
	return _str;
}

char &String::operator[](size_t i)
{
	if (i >= 0 && i < _size)
	{
		return _str[i];
	}
	else
	{
		cout << "String::operator[]——非法访问" << endl;
		exit(1);
	}
}

const char &String::operator[](size_t i) const
{
	if (i >= 0 && i < _size)
	{
		return _str[i];
	}
	else
	{
		cout << "String::operator[]——非法访问" << endl;
		exit(1);
	}
}

// 输入输出
ostream &operator<<(ostream &out, const String &s)
{
	for (size_t i = 0; i < s.size(); i++)
	{
		out << s[i];
	}
	return out;
}

istream &operator>>(istream &in, String &s)
{
	// char str[1024];
	// in.getline(str, sizeof(str));
	// size_t len = strlen(str);
	// s.reserve(len);
	// strcpy(s._str, str);
	// s._size = len;

	// 没有长度限制
	// 先清空之前的字符串
	s._size = 0;
	s._str[0] = '\0';
	while (1)
	{
		char ch;
		// in >> ch; 这样写会接受不到空格和换行
		ch = in.get();
		if (ch == ' ' || ch == '\n')
			break;
		else
			s += ch;
	}

	return in;
}

void String::getline()
{
	_size = 0;
	_str[0] = '\0';
	char ch;
	while (1)
	{
		cin.get(ch);
		if (ch == '\n')
			break;
		else
			*this += ch;
	}
}

void String::reserve(size_t n)
{
	if (n > _capacity)
	{
		char *newstr = new char[n + 1];
		strcpy(newstr, _str);
		delete[] _str;
		_str = newstr;
		_capacity = n;
	}
}

void String::resize(size_t n, char c)
{
	// 三种情况：n小于_size, n大于_size小于_capacity, n大于_capacity
	if (n < _size)
	{
		_str[n] = '\0';
		_size = n;
	}
	else
	{
		// 如果空间不够要增容
		if (n > _size)
			reserve(n);

		for (size_t i = _size; i < n; i++)
			_str[i] = c;

		_size = n;
		_str[_size] = '\0';
	}
}

void String::push_back(char c)
{
	// 空间不够增容
	if (_size == _capacity)
	{
		size_t newcapacity = _capacity == 0 ? 2 : _capacity * 2;
		reserve(newcapacity);
		// char *newstr = new char[newcapacity + 1];
		// strcpy(newstr, _str);
		// delete[] _str;
		// _str = newstr;
		// _capacity = newcapacity;
	}

	_str[_size] = c;
	++_size;
	// 因为字符没有\0，所以我们要手动加上它
	_str[_size] = '\0';

	//insert(_size, c);复用
}

void String::append(const char *str)
{
	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
		size_t newcapacity = _size + len;
		// char* newstr = new char[newcapacity + 1];
		// strcpy(newstr, _str);
		// delete[] _str;
		// _str = newstr;
		// _capacity = newcapacity;
		reserve(newcapacity);
	}

	strcpy(_str + _size, str);
	_size += len;

	//insert(_size, str);复用
}

String &String::operator+=(char c)
{
	this->push_back(c);
	return *this;
}

String &String::operator+=(const char *str)
{
	this->append(str);
	return *this;
}

String &String::erase(size_t pos, size_t len)
{
	// 如果从当前位置开始，要删除的长度已经大于已有字符的大小
	// 那么直接在pos位置赋值'\0'，就是删除成功了
	if (pos + len >= _size)
	{
		_str[pos] = '\0';
		_size = pos;
	}
	else
	{
		size_t i = pos + len;
		while (i <= _size)
		{
			_str[i - len] = _str[i];
			++i;
		}
		_size -= len;
	}
	return *this;
}

size_t String::find(char ch, size_t pos)
{
	if (pos < 0 && pos >= _size)
	{
		cout << "String::find——错误查找" << endl;
		exit(1);
	}

	for (size_t i = pos; i < _size; i++)
	{
		if (_str[i] == ch)
		{
			return i;
		}
	}
	return npos;
}

size_t String::find(const char *str, size_t pos)
{
	if (pos < 0 && pos >= _size)
	{
		cout << "String::find——错误查找" << endl;
		exit(1);
	}

	char *p = strstr(_str, str);
	if (p == nullptr)
		return npos;
	else
		return p - _str;
}

// 插入要注意，空间是否需要增容，\0是否要手动添加
String &String::insert(size_t pos, char c)
{
	if (pos > _size && pos < 0)
	{
		cout << "String::insert——错误下标" << endl;
		exit(1);
	}
	// 增容
	if (_size == _capacity)
	{
		size_t newcapacity = _capacity == 0 ? 2 : _capacity * 2;
		reserve(newcapacity);
	} 
	// 挪动数据
	int end = _size;
	while (end >= (int)pos)//这里pos不强转成int，end会优化成size_t，当pos=0时，end会变成负数，无符号的负数就是超大的正数
	{
		_str[end + 1] = _str[end];
		--end;
	}
	_str[pos] = c;
	++_size;

	return *this;
}

String &String::insert(size_t pos, const char *str)
{
	if (pos > _size && pos < 0)
	{
		cout << "String::insert——错误下标" << endl;
		exit(1);
	}
	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
		reserve(_size + len);
	}

	int end = _size;
	while (end >= (int)pos)
	{
		_str[end + len] = _str[end];
		--end;
	}
	// for (size_t i = 0; i < len; i++) _str[pos++] = str[i++];
	// 如果用strcpy，会把str的\0也拷过来，所以要用strncpy限定长度
	strncpy(_str + pos, str, len);
	_size += len;

	return *this;
}

bool String::operator<(const String &s)
{
	// strcmp >0:第一个大于第二个 <0:第一个小于于第二个 =0:第一个等于第二个
	int ret = strcmp(_str, s._str);
	return ret < 0;
}
bool String::operator==(const String &s)
{
	int ret = strcmp(_str, s._str);
	return ret == 0;
}
bool String::operator<=(const String &s)
{
	return *this < s || *this == s;
}
bool String::operator>(const String &s)
{
	return !(*this <= s);
}
bool String::operator>=(const String &s)
{
	return !(*this < s);
}
bool String::operator!=(const String &s)
{
	return !(*this == s);
}

// 将字符串转成整型
int String::StringToInt(char *str)
{
	int val = 0;
	for (size_t i = 0; i < _size; i++) //"12345"
	{
		val *= 10;
		val += (str[i] - '0');
	}

	return val;
}

// 析构函数
String::~String()
{
	delete[] _str;
	_str = nullptr;
	_size = _capacity = 0;
}